/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/6/28 15:40
  *
  * @file       pd_iwdg.c
  * @brief      Xxx hardware driver.
  *
  * @note       This file contains the hardware driver for the Xxx.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date          Author       Notes
  *   2024/6/28     Chris        the first version
  *
  ******************************************************************************
  */


#include <stm32f4xx_ll_iwdg.h>
#include <stm32f4xx_ll_rcc.h>
#include <stdlib.h>
#include "pd_iwdg.h"

static void IndepWDG_init_(const WDG *super) {
    IndepWDG *this = (IndepWDG *) super;

    LL_IWDG_EnableWriteAccess(this->IWDGx);
    LL_IWDG_SetPrescaler(this->IWDGx, this->Prescaler);
    /**
     * freq = LSI / Prescaler * (Counter + 1)
     * t = Prescaler * (Counter + 1) / LSI
     * reload = t * LSI / Prescaler - 1
     */
    LL_IWDG_SetReloadCounter(this->IWDGx, this->milliseconds * 32000 / 1000 / this->Prescaler - 1);
    LL_IWDG_Enable(this->IWDGx);
}

static void IndepWDG_feedDogs_(const WDG *super) {
    IndepWDG *this = (IndepWDG *) super;
    LL_IWDG_ReloadCounter(this->IWDGx);
}

static uint32_t IndepWDG_isReset_(const WDG *super) {
    return LL_RCC_IsActiveFlag_IWDGRST() == SET ? 1 : 0;
}

void IndepWDG_constructor(IndepWDG *this, IWDG_TypeDef *IWDGx, uint32_t Prescaler, uint32_t milliseconds) {
    static struct WDGVtbl vtbl = {
            .init      = &IndepWDG_init_,
            .feed_dogs = &IndepWDG_feedDogs_,
            .is_reset  = &IndepWDG_isReset_,
    };
    WDG_constructor(&this->wdg);
    this->wdg.vptr = &vtbl;

    this->IWDGx        = IWDGx;
    this->Prescaler    = Prescaler;
    this->milliseconds = milliseconds;
}

